home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-18 | 16.6 KB | 486 lines | [TEXT/MMCC] |
- /************************************************************************/
- /* Project...: Standard C++ Library */
- /* Name......: MWException.cp */
- /* Purpose...: portable exception handling */
- /* Copyright.: ©Copyright 1993-95 by metrowerks inc */
- /************************************************************************/
-
- #include <Types.h>
- #include <stdlib.h>
- #include <CPlusLib.h>
- #include <exception.h>
- #include <MWException.h>
-
- #ifndef __MC68K__ // defined in 68K startup code
-
- DestructorChain *__global_destructor_chain; // chain of global objects that need destruction
- ExceptionElement *__local_destructor_chain; // chain of local objects that need destruction
-
- #endif
-
- static char catch_buffer[CATCH_BUFSIZE];
- void *__catch_buffer = (void *)catch_buffer;
- void *__catch_var_pointer;
- char *__throw_type;
-
- static terminate_handler thandler; // pointer to terminate handler function
- static unexpected_handler uhandler; // pointer to unexpected handler function
-
- /************************************************************************/
- /* Purpose..: Set a terminate handler function */
- /* Input....: pointer to terminate handler function */
- /* Return...: --- */
- /************************************************************************/
- extern terminate_handler set_terminate(terminate_handler handler)
- {
- terminate_handler old=thandler; thandler=handler; return old;
- }
-
- /************************************************************************/
- /* Purpose..: Terminate exception handling */
- /* Input....: --- */
- /* Return...: --- (shall not return to caller) */
- /************************************************************************/
- extern void terminate()
- {
- if(thandler) thandler(); abort();
- }
-
- /************************************************************************/
- /* Purpose..: Set an unexpected handler function */
- /* Input....: pointer to unexpected handler function */
- /* Return...: --- */
- /************************************************************************/
- extern unexpected_handler set_unexpected(unexpected_handler handler)
- {
- unexpected_handler old=uhandler; uhandler=handler; return old;
- }
-
- /************************************************************************/
- /* Purpose..: Handle unexpected exception */
- /* Input....: --- */
- /* Return...: --- (shall not return to caller) */
- /************************************************************************/
- extern void unexpected()
- {
- if(uhandler) uhandler(); terminate();
- }
-
- /************************************************************************/
- /* Purpose..: Create a new exception state */
- /* Input....: pointer to uninitialized exception state */
- /* Input....: pointer to excpetion buffer */
- /* Return...: --- */
- /************************************************************************/
- extern void __new_exception_state(ExceptionState *newp,char *buffer)
- {
- newp->ldc_save = 0;
- newp->cb_save = buffer;
- newp->cvp_save = 0;
- newp->tt_save = __throw_type;
- newp->reserved = 0;
- }
-
- /************************************************************************/
- /* Purpose..: Switch to a new exception state */
- /* Input....: pointer to new exception state */
- /* Input....: pointer to exception state save buffer */
- /* Return...: --- */
- /************************************************************************/
- extern void __switch_exception_state(ExceptionState *newp,ExceptionState *savep)
- {
- // save current state
- savep->ldc_save = __local_destructor_chain;
- savep->cb_save = __catch_buffer;
- savep->cvp_save = __catch_var_pointer;
- savep->tt_save = __throw_type;
-
- // set new state
- __local_destructor_chain = newp->ldc_save;
- __catch_buffer = newp->cb_save;
- __catch_var_pointer = newp->cvp_save;
- __throw_type = newp->tt_save;
- }
-
- /************************************************************************/
- /* Purpose..: Register a global object for later destruction */
- /* Input....: pointer to global object */
- /* Input....: pointer to destructor function */
- /* Input....: pointer to global registration structure */
- /* Return...: pointer to global object (pass thru) */
- /************************************************************************/
- extern void *__register_global_object(void *object,void *destructor,void *regmem)
- {
- ((DestructorChain *)regmem)->next=__global_destructor_chain;
- ((DestructorChain *)regmem)->destructor=destructor;
- ((DestructorChain *)regmem)->object=object;
- __global_destructor_chain=(DestructorChain *)regmem;
-
- return object;
- }
-
- /************************************************************************/
- /* Purpose..: Register an automatic data object for later destruction */
- /* Input....: pointer to automatic object */
- /* Input....: pointer to destructor function */
- /* Input....: pointer to ExceptionElement structure */
- /* Return...: pointer to automatic object (pass thru) */
- /************************************************************************/
- void *__register_auto_object(void *object,void *destructor,void *regmem)
- {
- ((ExceptionElement *)regmem)->type = EET_AUTODESTROY;
- ((ExceptionElement *)regmem)->next = __local_destructor_chain;
- ((ExceptionElement *)regmem)->data.autodestroy.destructor = destructor;
- ((ExceptionElement *)regmem)->data.autodestroy.object = object;
- __local_destructor_chain=(ExceptionElement *)regmem;
-
- return object;
- }
-
- /************************************************************************/
- /* Purpose..: Register a temporary data object for later destruction */
- /* Input....: pointer to temporary object */
- /* Input....: pointer to destructor function */
- /* Input....: pointer to ExceptionElement structure */
- /* Return...: pointer to temporary object (pass thru) */
- /************************************************************************/
- extern void *__register_temp_object(void *object,void *destructor,void *regmem)
- {
- ((ExceptionElement *)regmem)->type = EET_TEMPDESTROY;
- ((ExceptionElement *)regmem)->next = __local_destructor_chain;
- ((ExceptionElement *)regmem)->data.autodestroy.destructor = destructor;
- ((ExceptionElement *)regmem)->data.autodestroy.object = object;
- __local_destructor_chain=(ExceptionElement *)regmem;
-
- return object;
- }
-
- /************************************************************************/
- /* Purpose..: Pre register a temporary data object */
- /* Input....: pointer to temporary object */
- /* Input....: pointer to destructor function */
- /* Input....: pointer to ExceptionElement structure */
- /* Return...: pointer ExceptionElement structure */
- /************************************************************************/
- extern void *__preregister_temp_object(void *object,void *destructor,void *regmem)
- {
- //
- // Note: This function is used to register an object that will be constructed
- // by a return statement. The result of this function will be passed to
- // the function return temp memory argument.
- //
- ((ExceptionElement *)regmem)->type = EET_TEMPDESTROY;
- ((ExceptionElement *)regmem)->next = __local_destructor_chain;
- ((ExceptionElement *)regmem)->data.autodestroy.destructor = destructor;
- ((ExceptionElement *)regmem)->data.autodestroy.object = object;
- __local_destructor_chain=(ExceptionElement *)regmem;
-
- return regmem;
- }
-
- /************************************************************************/
- /* Purpose..: Re-register a temporary data object */
- /* Input....: pointer to local ExceptionElement structure */
- /* Return...: pointer to temporary object */
- /************************************************************************/
- extern void *__reregister_temp_object(void *regmem)
- {
- //
- // Note: This function will register a preregistered local object for destruction.
- // It will be called before a return object is initialized via return <x>;
- //
- ((ExceptionElement *)regmem)->type = EET_TEMPDESTROY;
- return ((ExceptionElement *)regmem)->data.autodestroy.object;
- }
-
- /************************************************************************/
- /* Purpose..: Destroy all constructed global objects */
- /* Input....: --- */
- /* Return...: --- */
- /************************************************************************/
- #ifndef __MC68K__ // defined in 68K startup code
-
- void __destroy_global_chain(void)
- {
- DestructorChain *gdc;
-
- while((gdc=__global_destructor_chain)!=0L)
- {
- __global_destructor_chain=gdc->next;
- ((ConstructorDestructor)gdc->destructor)(gdc->object,-1);
- }
- }
-
- #endif
-
- /************************************************************************/
- /* Purpose..: Destroy one or more temporary objects */
- /* Input....: pointer to last destroyed objects ExceptionElement */
- /* Return...: --- */
- /************************************************************************/
- extern void __destroy_temp_objects(void *lastregmem)
- {
- ExceptionElement *eep,*neep;
-
- while((eep=__local_destructor_chain)!=0L)
- {
- if(eep->type==EET_TEMPDESTROY)
- {
- __local_destructor_chain=eep->next;
- ((ConstructorDestructor)eep->data.autodestroy.destructor)(eep->data.autodestroy.object,-1);
- if((void *)eep==lastregmem) return;
- }
- else break;
- }
-
- __local_destructor_chain=eep; // this will remain the top element
-
- for(;;)
- {
- if((neep=eep->next)==0L) return;
- if(neep->type==EET_TEMPDESTROY)
- {
- eep->next=neep->next;
- ((ConstructorDestructor)neep->data.autodestroy.destructor)(neep->data.autodestroy.object,-1);
- if((void *)neep==lastregmem) return;
- }
- else eep=neep;
- }
- }
-
- /************************************************************************/
- /* Purpose..: Destroy one or more automatic/temporary objects */
- /* Input....: pointer to last destroyed objects ExceptionElement */
- /* Return...: --- */
- /************************************************************************/
- extern void __destroy_autotemp_objects(void *lastregmem)
- {
- ExceptionElement *eep;
-
- while((eep=__local_destructor_chain)!=0L)
- {
- __local_destructor_chain=eep->next;
- switch(eep->type)
- {
- case EET_AUTODESTROY:
- case EET_TEMPDESTROY:
- ((ConstructorDestructor)eep->data.autodestroy.destructor)(eep->data.autodestroy.object,-1);
- break;
-
- // case EET_PREAUTODESTROY:
- // case EET_CATCHBLOCK:
- // break;
- }
- if((void *)eep==lastregmem) return;
- }
- }
-
- /************************************************************************/
- /* Purpose..: Destroy some constructed local objects */
- /* Input....: pointer to first non-destroyed ExceptionElement */
- /* Return...: --- */
- /************************************************************************/
- extern void __destroy_autotemp_objects_to(void *lastregmem)
- {
- ExceptionElement *eep;
-
- while((eep=__local_destructor_chain)!=0L)
- {
- if((void *)eep==lastregmem) return;
- __local_destructor_chain=eep->next;
- switch(eep->type)
- {
- case EET_AUTODESTROY:
- case EET_TEMPDESTROY:
- ((ConstructorDestructor)eep->data.autodestroy.destructor)(eep->data.autodestroy.object,-1);
- break;
-
- // case EET_PREAUTODESTROY:
- // case EET_CATCHBLOCK:
- // break;
- }
- }
- }
-
- /************************************************************************/
- /* Purpose..: Destroy all constructed local objects */
- /* Input....: pointer to chain */
- /* Return...: --- */
- /************************************************************************/
- extern void __destroy_local_chain(void)
- {
- ExceptionElement *eep;
-
- while((eep=__local_destructor_chain)!=0L)
- {
- __local_destructor_chain=eep->next;
- switch(eep->type)
- {
- case EET_AUTODESTROY:
- case EET_TEMPDESTROY:
- ((ConstructorDestructor)eep->data.autodestroy.destructor)(eep->data.autodestroy.object,-1);
- break;
-
- // case EET_PREAUTODESTROY:
- // case EET_CATCHBLOCK:
- // break;
- }
- }
- }
-
- /************************************************************************/
- /* Purpose..: Dummy function (does nothing) */
- /* Input....: --- */
- /* Return...: --- */
- /************************************************************************/
- extern void __dummy(void)
- {
- }
-
- /************************************************************************/
- /* Purpose..: Throw an exception */
- /* Input....: pointer to thrown type id string (0: throw;) */
- /* Return...: --- */
- /************************************************************************/
- extern void __throw(char *throwtype)
- {
- ExceptionElement *eep;
- char *cptr1,*cptr2;
- CatchData *catchdata;
- long offset;
-
- if(throwtype==0)
- { // throw;
- if((throwtype=__throw_type)==0) terminate();
- }
- else __throw_type=throwtype;
-
- for(eep=__local_destructor_chain; eep; eep=eep->next) if(eep->type==EET_CATCHBLOCK)
- {
- if((cptr2=eep->data.catchblock.catchtype)==0) goto catchit; // catch(...)
- cptr1=throwtype;
- switch(*cptr1)
- {
- case '*':
- case '!':
- if(*cptr1++==*cptr2++) for(;;)
- { // class name compare loop
- if(*cptr1==*cptr2++)
- {
- if(*cptr1++=='!')
- { // class match found / get offset
- for(offset=0; *cptr1!='!';) offset=offset*10+*cptr1++-'0';
- goto catchit;
- }
- }
- else
- {
- while(*cptr1++!='!') ; // skip class name
- while(*cptr1++!='!') ; // skip offset
- if(*cptr1==0) break; // break if no more class names
- cptr2=eep->data.catchblock.catchtype+1; // retry with next class name
- }
- }
- break;
-
- default:
- for(; *cptr1==*cptr2; cptr1++,cptr2++) if(*cptr1==0) goto catchit;
- break;
- }
- }
- terminate(); // no matching catcher found
-
- catchit:
- catchdata=eep->data.catchblock.catchdata;
- switch(*throwtype)
- {
- case '!': // class match (directly adjust offset)
- __catch_var_pointer=(char *)__catch_buffer+offset; break;
-
- case '*': // pointer match (create a pointer copy with adjusted offset)
- __catch_var_pointer=(char *)__catch_buffer+sizeof(void *);
- *(long *)__catch_var_pointer=*(long *)__catch_buffer+offset; break;
-
- default: // traditional match
- __catch_var_pointer=__catch_buffer; break;
- }
-
- // destroy all temporary objects and remove catchers
-
- while(!eep->data.catchblock.catchdata->last_catch)
- { // skip all catchers that belong to this catch block
- if((eep=eep->next)==0 || eep->type!=EET_CATCHBLOCK) terminate();
- }
- __destroy_autotemp_objects(eep);
-
- // longjmp to catcher
-
- __catch_jump(catchdata->catch_buffer,catchdata->catch_pc);
- }
-
- /************************************************************************/
- /* Purpose..: Install an exception catcher */
- /* Input....: true: first catcher in a set of catchers */
- /* Input....: pointer to exception element (uninitialized) */
- /* Input....: pointer to catch data structure (uninitialized) */
- /* Input....: pointer to catch register buffer (initialized) */
- /* Input....: pointer to catcher pc */
- /* Input....: pointer to catcher type string */
- /* Return...: --- */
- /************************************************************************/
- extern void __install_catcher(long last_catch,ExceptionElement *eep,CatchData *catchdata,CatchRegBuffer *catch_buffer,void *catch_pc,char *catchtype)
- {
- catchdata->catch_pc = catch_pc;
- catchdata->catch_buffer = catch_buffer;
- catchdata->last_catch = last_catch;
-
- eep->type = EET_CATCHBLOCK;
- eep->next = __local_destructor_chain;
- eep->data.catchblock.catchtype = catchtype;
- eep->data.catchblock.catchdata = catchdata;
- __local_destructor_chain=eep;
- }
-
- #if defined(__MC68K__)
-
- /************************************************************************/
- /* Purpose..: Save non-volatile registers into a buffer */
- /* Input....: pointer to catch register buffer */
- /* Return...: --- */
- /************************************************************************/
- extern asm void __setup_catchregbuffer(CatchRegBuffer *crp)
- {
- movea.l (sp)+,a1 // pop return address into a1
- movea.l (sp),a0 // load crp into a0
- movem.l d3-d7/a2-a4/a6-a7,(a0) // save non-volatile registers
- jmp (a1) // return to caller
- }
-
- /************************************************************************/
- /* Purpose..: Restore non-volatile registers an d jump to catcher */
- /* Input....: pointer to catch register buffer */
- /* Input....: pointer to catcher routine */
- /* Return...: --- (does not return to caller) */
- /************************************************************************/
- extern asm void __catch_jump(CatchRegBuffer *crp,void *pc)
- {
- addq.l #4,sp // pop return address
- movea.l (sp)+,a0 // pop crp into a0
- movea.l (sp),a1 // load pc into a1
- movem.l (a0),d3-d7/a2-a4/a6-a7 // restore non-volatile registers
- addq.l #4,sp // adjust stack pointer (remove __setup_catchregbuffer's crp)´
- jmp (a1) // jump to catcher
- }
-
- #elif defined(__POWERPC__)
-
- // ???
-
- #elif defined(__INTEL__)
-
- // ???
-
- #else
- #error
- #endif
-